package structs;

import java.util.ArrayList;


import interfaces.ICard;
import interfaces.IPlayer;
import interfaces.Strategy;

public class SmarterStrategy implements Strategy {

	private Game game;
	private IPlayer opponent;
	private IPlayer ai;

	//Current Hand
	private ArrayList<ICard> lowLife;
	private ArrayList<ICard> highLife;
	
	private ICard hand1;
	private ICard hand2;
	private ICard hand3;

	//Deck
	private ArrayList<ICard> highLifeCards;
	private ArrayList<ICard> lowLifeCards;
	
	private ArrayList<ICard> highCards;
	private ArrayList<ICard> lowCards;
	
	private ArrayList<ICard> suit1HighCards;
	private ArrayList<ICard> suit1LowCards;
	private ArrayList<ICard> suit1ElseCards;
	
	private ArrayList<ICard> suit2HighCards;
	private ArrayList<ICard> suit2LowCards;
	private ArrayList<ICard> suit2ElseCards;
	
	private ArrayList<ICard> suit3HighCards;
	private ArrayList<ICard> suit3LowCards;
	private ArrayList<ICard> suit3ElseCards;

	public SmarterStrategy(Game game){
		this.game = game;
	}

	public ICard nextMove() {
		this.setup();

		return this.decide();
	}

	private void setup(){
		ai = this.game.getAIPlayer();
		opponent = null;
		Deck deck = this.game.getDeck();

		for(IPlayer player : this.game.getPlayers()){
			if(player != ai){
				opponent = player;
			}
		}

		lowLife = new ArrayList<ICard>();
		highLife = new ArrayList<ICard>();
		highLifeCards = new ArrayList<ICard>();
		lowLifeCards = new ArrayList<ICard>();
		highCards = new ArrayList<ICard>();
		lowCards = new ArrayList<ICard>();
		suit1HighCards = new ArrayList<ICard>();
		suit1LowCards = new ArrayList<ICard>();
		suit1ElseCards = new ArrayList<ICard>();
		suit2HighCards = new ArrayList<ICard>();
		suit2LowCards = new ArrayList<ICard>();
		suit2ElseCards = new ArrayList<ICard>();
		suit3HighCards = new ArrayList<ICard>();
		suit3LowCards = new ArrayList<ICard>();
		suit3ElseCards = new ArrayList<ICard>();

		//Current hand
		//		for(ICard card : ai.getCurrentHand()){
		//			if(card.getSuit().equalsIgnoreCase(deck.getLife().getSuit())){
		//				if(card.getPoints() > 3){
		//					this.highLife.add(card);
		//				}
		//				else{
		//					this.lowLife.add(card);
		//				}
		//			}
		//		}
		//
		//		for(ICard card : deck.getCards()){
		//			if(card.getSuit().equalsIgnoreCase(deck.getLife().getSuit())){
		//				if(card.getPoints() > 3){
		//					this.highLifeCards.add(card);
		//				}
		//				else{
		//					this.lowLifeCards.add(card);
		//				}	
		//			}
		//			else{
		//				if(card.getPoints() > 3){
		//					this.highCards.add(card);
		//				}
		//				else{
		//					this.lowCards.add(card);
		//				}
		//			}
		//		}
		//
		//		this.hand1 = ai.getCurrentHand().get(0);
		//
		//		for(ICard card : deck.getCards()){
		//			if(card.getSuit().equalsIgnoreCase(this.hand1.getSuit())){
		//				if(card.getPoints() > this.hand1.getPoints()){
		//					this.suit1HighCards.add(card);
		//				}
		//				else{
		//					this.suit1LowCards.add(card);
		//				}	
		//			}
		//			else{
		//				this.suit1ElseCards.add(card);
		//			}
		//		}
		//
		//		this.hand2 = ai.getCurrentHand().get(1);
		//
		//		for(ICard card : deck.getCards()){
		//			if(card.getSuit().equalsIgnoreCase(this.hand2.getSuit())){
		//				if(card.getPoints() > this.hand2.getPoints()){
		//					this.suit2HighCards.add(card);
		//				}
		//				else{
		//					this.suit2LowCards.add(card);
		//				}	
		//			}
		//			else{
		//				this.suit2ElseCards.add(card);
		//			}
		//		}
		//
		//		this.hand3 = ai.getCurrentHand().get(2);
		//
		//		for(ICard card : deck.getCards()){
		//			if(card.getSuit().equalsIgnoreCase(this.hand3.getSuit())){
		//				if(card.getPoints() > this.hand3.getPoints()){
		//					this.suit3HighCards.add(card);
		//				}
		//				else{
		//					this.suit3LowCards.add(card);
		//				}	
		//			}
		//			else{
		//				this.suit3ElseCards.add(card);
		//			}
		//		}
	}

	private ICard decide(){
		ICard oHand = this.opponent.getPlayedCard();
		ICard possible = null;

		//FIXME variable "possible" swapping not working accordingly in reacting

		if(this.game.getAIPosition() == 2){
			//Reacting to played hand
			if( this.game.getDeck().getLife().getSuit().equalsIgnoreCase( oHand.getSuit() ) ){
				//Op played life
				if(oHand.getPoints() > 3){
					//Played high value life card
					for(ICard card : this.ai.getCurrentHand()){
						if(
								possible == null &&
								card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) && 
								card.getPoints() > oHand.getPoints()
						){
							possible = card;
						}
						else if(
								card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) && 
								card.getPoints() > oHand.getPoints() && 
								card.getPoints() <= possible.getPoints()
						){
							//card is also life and larger and lower than other cards
							possible = card;
						}
					}
					
					//Dont have life
					for(ICard card : this.ai.getCurrentHand()){
						if(possible == null){
							possible = card;
						}
						if(card.getPoints() <= possible.getPoints()){
							possible = card;
						}
					}

				}
				else{
					for(ICard card : this.ai.getCurrentHand()){
						if(
								possible == null &&
								card.getPoints() <= 3 && 
								!card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit())
						){
							possible = card;
						}
						else if(
								possible != null &&
								card.getPoints() <= possible.getPoints() && 
								card.getPoints() <= 3 && 
								!card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit())
						){
							//Found low value card and isn't life
							possible = card;
						}
					}

					//Dont have low value cards, find high value life card
					if(possible == null ){
						for(ICard card : this.ai.getCurrentHand()){
							if( 	
									possible == null &&
									card.getPoints() > 3 && 
									card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit())
							){
								possible = card;
							}
							else if(
									possible != null &&
									card.getPoints() > possible.getPoints() && 
									card.getPoints() > 3 && 
									card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit())
							){							
								possible = card;
							}
						}
					}

				}

			}
			else{
				if(oHand.getPoints() > 3){
					//Played high value card

					//Look for higher value
					for(ICard card : this.ai.getCurrentHand()){
						if(
								possible == null &&
								card.getSuit().equalsIgnoreCase(oHand.getSuit()) && 
								card.getPoints() > oHand.getPoints()
						){
							possible = card;
						}
						else if(
								possible != null &&
								card.getSuit().equalsIgnoreCase(oHand.getSuit()) && 
								card.getPoints() > oHand.getPoints() &&
								card.getPoints() < possible.getPoints()
						){							
							possible = card;
						}
					}

					//Dont have higher value cards, find high value life card
					for(ICard card : this.ai.getCurrentHand()){
						if(
								possible == null &&
								card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) && 
								card.getPoints() >= 2
						){
							possible = card;
						}

						else if(
								possible != null &&
								card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) && 
								card.getPoints() >= 2 &&
								card.getPoints() < possible.getPoints()
						){							
							possible = card;
						}
					}

					//Look for low value
					if(possible == null ){
						for(ICard card : this.ai.getCurrentHand()){
							if(card.getPoints() < 3){							
								possible = card;
							}
						}
					}

				}
				else{
					//Look for higher value
					for(ICard card : this.ai.getCurrentHand()){
						if(
								possible == null &&
								card.getSuit().equalsIgnoreCase(oHand.getSuit()) && 
								card.getPoints() > oHand.getPoints()
						){
							possible = card;
						}

						else if(
								possible != null &&
								card.getSuit().equalsIgnoreCase(oHand.getSuit()) && 
								card.getPoints() > oHand.getPoints() &&
								card.getPoints() < possible.getPoints()
						){							
							possible = card;
						}
					}

					//Look for low value
					if(possible == null ){
						for(ICard card : this.ai.getCurrentHand()){
							if(card.getPoints() < 3){							
								possible = card;
							}
						}
					}
				}
			}
			//Strange case where hand is all highs
			if(possible == null){
				for(ICard card : this.ai.getCurrentHand()){
					if(
							card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) &&
							possible == null
					){							
						possible = card;
					}
					else if(
							possible != null &&
							card.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) &&
							card.getPoints() < possible.getPoints()
					){
						possible = card;
					}
				}
				//All lives
				if(possible == null){
					for(ICard card : this.ai.getCurrentHand()){
						if(
								possible == null
						){							
							possible = card;
						}
						else if(
								possible != null &&
								card.getPoints() < possible.getPoints()
						){
							possible = card;
						}
					}
				}
			}
		}
		else{
			//Acting

			//Use minimax instead
			Strategy mm = new MinimaxStrategy(this.game);

			return mm.nextMove();


			//			Deck deck = this.game.getDeck();
			//			ArrayList<ICard> currentHand = this.game.getAIPlayer().getCurrentHand();
			//			ICard bestPossible = null;
			//
			//			float highProb = (float) this.highCards.size()/(deck.cardsLeft());
			////			float lowProb = (float) this.lowCards.size()/(deck.cardsLeft());
			//
			//			if(highProb > 0.4){
			//				//Check if have life
			//				float highLifeProb = (float) this.highLifeCards.size()/deck.cardsLeft();
			//
			//				if(!this.lowLife.isEmpty() || !this.highLife.isEmpty()){
			//					//Check low life
			//					if(!this.lowLife.isEmpty()){
			//						for(ICard card : this.lowLife){
			//							if(bestPossible == null){ 
			//								bestPossible = card;
			//							}
			//							if(bestPossible.getPoints() > card.getPoints()){
			//								bestPossible = card;
			//							}
			//						}
			//					}
			//					else if(highLifeProb < 0.3 && highProb > 0.6){
			//						for(ICard card : this.highLife){
			//							if(bestPossible == null){ 
			//								bestPossible = card;
			//							}
			//							if(bestPossible.getPoints() < card.getPoints()){
			//								bestPossible = card;
			//							}
			//						}
			//					}
			//				}
			//
			//				//Check for all others who has best prob of highs
			//
			//
			//			}
			//			else {
			//				for(ICard card : currentHand){
			//					//Low cards that aren't life
			//					if(card.getPoints() < 3 && !card.getSuit().equalsIgnoreCase(deck.getLife().getSuit())){
			//						if(bestPossible == null){
			//							bestPossible = card;
			//						}
			//						else if( bestPossible.getPoints() > card.getPoints() ){
			//							bestPossible = card;
			//						}
			//					}
			//				}
			//				//No low cards, search for low life
			//				if(bestPossible == null){
			//					for(ICard card : currentHand){
			//
			//						if(card.getPoints() < 3 && card.getSuit().equalsIgnoreCase(deck.getLife().getSuit())){
			//							if(bestPossible == null){
			//								bestPossible = card;
			//							}
			//							else if( bestPossible.getPoints() > card.getPoints() ){
			//								bestPossible = card;
			//							}
			//						}
			//					}
			//				}
			//
			//				//No low life cards, search for lowest high that isn't life
			//				if(bestPossible == null){
			//					for(ICard card : currentHand){
			//
			//						if(!card.getSuit().equalsIgnoreCase(deck.getLife().getSuit())){
			//							if(bestPossible == null){
			//								bestPossible = card;
			//							}
			//							else if( bestPossible.getPoints() > card.getPoints() ){
			//								bestPossible = card;
			//							}
			//						}
			//
			//					}
			//				}
			//			}

			//return bestPossible;

		}

		return possible;
	}

}
